home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 49
/
Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso
/
Aminet
/
util
/
sys
/
AmberRAM.lha
/
AmberRAM
/
Source
/
filesystem.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-02-27
|
28KB
|
1,359 lines
/*
File: filesystem.c
Author: Neil Cafferkey
Copyright (C) 2001-2002 Neil Cafferkey
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/
#include "handler_protos.h"
/****i* ram.handler/CreateObject *******************************************
*
* NAME
* CreateObject --
*
* SYNOPSIS
* object = CreateObject(handler,name,type,
* parent)
*
* struct Object *CreateObject(struct Handler *,TEXT *,BYTE,
* struct Object *);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
struct Object *CreateObject(struct Handler *handler,const TEXT *name,
BYTE type,struct Object *parent)
{
struct Object *object;
LONG error;
UPINT block_count;
/* Check for an existing object with the same name */
error=0;
object=NULL;
if(parent!=NULL)
{
parent=GetRealObject(parent);
object=(APTR)FindNameNoCase((struct List *)&parent->elements,name);
}
/* Create a new object structure */
if(object==NULL)
{
object=AllocMem(sizeof(struct Object),MEMF_CLEAR);
if(object==NULL)
error=ERROR_DISK_FULL;
if(error==0)
{
block_count=MEMBLOCKS(sizeof(struct Object));
object->block_count=MEMBLOCKS(sizeof(struct Object));
handler->block_count+=MEMBLOCKS(sizeof(struct Object));
NewList((struct List *)&object->elements);
((struct Node *)object)->ln_Pri=type;
object->parent=parent;
DateStamp(&object->date);
if(name!=NULL)
{
name=FilePart(name);
if(!SetName(handler,object,name))
error=IoErr();
}
if(parent!=NULL)
{
AddTail((struct List *)&parent->elements,(struct Node *)object);
CopyMem(&object->date,&parent->date,sizeof(struct DateStamp));
}
}
}
else
{
error=ERROR_OBJECT_EXISTS;
}
if(error==0)
MatchNotifyRequests(handler);
if(error!=0)
{
DeleteObject(handler,object);
object=NULL;
}
/* Return the new object */
SetIoErr(error);
return object;
}
/****i* ram.handler/DeleteObject *******************************************
*
* NAME
* DeleteObject --
*
* SYNOPSIS
* success = DeleteObject(handler,object)
*
* BOOL DeleteObject(struct Handler *,struct Object *);
*
* FUNCTION
*
* INPUTS
* object - the object to be deleted, or NULL for no action.
*
* RESULT
* success - success indicator.
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
BOOL DeleteObject(struct Handler *handler,struct Object *object)
{
LONG error=0;
BYTE object_type;
struct Lock *lock;
struct Block *block;
struct MinNode *node;
struct Object *real_object,*master_link,*heir,*dir;
PINT block_diff;
if(object!=NULL)
{
real_object=GetRealObject(object);
/* Check for a non-empty, unlinked directory */
object_type=((struct Node *)object)->ln_Pri;
if((object_type==ST_USERDIR)&&(object->hard_link.mln_Succ==NULL)
&&!IsListEmpty((struct List *)&object->elements))
error=ERROR_DIRECTORY_NOT_EMPTY;
/* Ensure the object isn't in use */
lock=LockObject(handler,object,ACCESS_WRITE);
if(lock==NULL)
error=IoErr();
CmdFreeLock(handler,lock);
if(error==0)
{
/* Remove the object from its directory */
if(object->parent!=NULL)
Remove((struct Node *)object);
/* Delete a hard link */
if((object_type==ST_LINKFILE)||(object_type==ST_LINKDIR))
{
node=real_object->hard_link.mln_Succ;
master_link=HARDLINK(node);
Remove((APTR)&object->hard_link);
if(object==master_link)
{
node=node->mln_Succ;
if(node->mln_Succ!=NULL)
{
master_link=HARDLINK(node);
while((node=(APTR)RemHead((APTR)&object->elements))!=NULL)
AddTail((APTR)&master_link->elements,(APTR)node);
}
else
{
real_object->hard_link.mln_Succ=NULL;
real_object->hard_link.mln_Pred=NULL;
}
}
}
/* Delete a linked object */
else if((node=object->hard_link.mln_Succ)!=NULL)
{
master_link=HARDLINK(node);
heir=HARDLINK(RemTail((APTR)&master_link->elements));
/* Swap names and comments */
block_diff=SwapStrings(&((struct Node *)heir)->ln_Name,
&((struct Node *)object)->ln_Name);
block_diff+=SwapStrings(&heir->comment,&object->comment);
object->block_count+=block_diff;
heir->block_count-=block_diff;
/* Put object in its new directory */
object->parent=heir->parent;
AddTail((APTR)&object->parent->elements,(APTR)object);
if(heir==master_link)
{
real_object->hard_link.mln_Succ=NULL;
real_object->hard_link.mln_Pred=NULL;
}
/* Prepare to destroy "heir" link */
Remove((APTR)heir);
object=heir;
}
/* Delete the root directory and all other objects */
else if(object_type==ST_ROOT)
{
dir=object;
while(dir!=NULL)
{
object=(APTR)RemHead((struct List *)&dir->elements);
if(object==NULL)
{
object=dir;
dir=dir->parent;
if(dir!=NULL)
DeleteObject(handler,object);
}
else if(((struct Node *)object)->ln_Pri==ST_USERDIR)
{
dir=object;
}
else
{
DeleteObject(handler,object);
}
}
}
/* Delete an unlinked object */
else
{
/* Remove all blocks if the object is a file */
while((block=(APTR)RemTail((struct List *)&object->elements))
!=NULL)
FreeMem(block,sizeof(struct Block)+block->length);
}
/* Free object's memory */
SetString(&((struct Node *)object)->ln_Name,NULL);
SetString(&object->comment,NULL);
handler->block_count-=object->block_count;
FreeMem(object,sizeof(struct Object));
}
}
/* Return result */
SetIoErr(error);
return error==0;
}
/****i* ram.handler/GetObject **********************************************
*
* NAME
* GetObject --
*
* SYNOPSIS
* object = GetObject(handler,lock,name,
* parent)
*
* struct Object *GetObject(struct Handler *,struct Lock *,TEXT *,
* struct Object **);
*
* FUNCTION
*
* INPUTS
* lock - .
* name - .
* parent - .
*
* RESULT
* object - The located object.
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
struct Object *GetObject(struct Handler *handler,
struct Lock *lock,const TEXT *name,struct Object **parent)
{
const TEXT *p;
TEXT ch,buffer[256];
PINT pos;
struct Object *object,*old_object;
old_object=NULL;
for(ch=*(p=name);(ch!=':')&&(ch!='\0');ch=*(++p));
if(ch==':')
name=p+1;
/* Get object referenced by lock */
lock=FixLock(handler,lock);
object=(APTR)((struct FileLock *)lock)->fl_Key;
/* Traverse textual portion of path */
pos=0;
while((pos!=-1)&&(object!=NULL))
{
pos=SplitName(name,'/',buffer,pos,256);
if(*buffer!='\0')
{
old_object=object;
if(((struct Node *)object)->ln_Pri>0)
{
object=GetRealObject(object);
object=(struct Object *)
FindNameNoCase((struct List *)&object->elements,buffer);
}
else
{
object=NULL;
old_object=NULL;
}
}
else if(pos!=-1)
{
object=object->parent;
}
}
/* Record the parent directory of the supplied path, if it exists */
if(parent!=NULL)
{
if(pos==-1)
*parent=old_object;
else
*parent=NULL;
}
/* Return the located object */
SetIoErr(ERROR_OBJECT_NOT_FOUND);
return object;
}
/****i* ram.handler/ChangeFileSize *****************************************
*
* NAME
* ChangeFileSize --
*
* SYNOPSIS
* new_size = ChangeFileSize(handler,opening,offset,
* mode)
*
* PINT ChangeFileSize(struct Handler *,struct Opening *,PINT,
* LONG);
*
* FUNCTION
* If there is not enough space for the requested size, the file size
* will remain at its initial value and -1 will be returned.
*
*
*
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
PINT ChangeFileSize(struct Handler *handler,struct Opening *opening,
PINT offset,LONG mode)
{
PINT length,new_length,remainder,end_length,full_length;
UPINT diff,old_pos,block_count;
struct Block *block,*end_block;
struct Object *file;
LONG error=0;
/* Get origin */
file=opening->file;
if(mode==OFFSET_BEGINNING)
new_length=0;
else if(mode==OFFSET_CURRENT)
new_length=opening->pos;
else
new_length=file->length;
if(-offset>new_length)
{
SetIoErr(ERROR_SEEK_ERROR);
return -1;
}
new_length+=offset;
length=file->length;
block_count=file->block_count;
old_pos=opening->pos;
full_length=length;
end_length=file->end_length;
block=(struct Block *)file->elements.mlh_TailPred;
if(end_length!=0)
{
full_length+=block->length-end_length;
}
if(new_length>length)
{
/* Add the required number of data bytes */
remainder=new_length-full_length;
end_length-=remainder;
while(remainder>0)
{
block=AddDataBlock(handler,file,remainder);
if(block!=NULL)
{
end_length=remainder;
remainder-=block->length;
}
else
remainder=0;
}
/* Remove new blocks upon failure */
if(block==NULL)
{
new_length=-1;
error=IoErr();
ChangeFileSize(handler,opening,length,OFFSET_BEGINNING);
}
else
file->end_length=end_length;
}
else if(length!=new_length)
{
/* Remove surplus blocks from the file */
block=NULL;
while(full_length>new_length)
{
FreeDataBlock(file,block);
block=(APTR)RemTail((APTR)&file->elements);
full_length-=block->length;
}
end_block=(APTR)file->elements.mlh_TailPred;
if((APTR)end_block!=(APTR)&file->elements)
end_length=end_block->length;
else
end_length=0;
file->end_length=end_length;
/* Allocate a suitably sized end block and copy old data to it */
diff=new_length-full_length;
file->length=full_length;
CmdSeek(opening,0,OFFSET_END);
if(ChangeFileSize(handler,opening,diff,OFFSET_END)!=-1)
{
WriteData(handler,opening,((UBYTE *)block)+sizeof(struct Block),
diff);
FreeDataBlock(file,block);
}
else
AddTail((struct List *)&file->elements,(APTR)block);
/* Ensure opening's position isn't past new EOF */
if(opening->pos>new_length)
{
opening->block=(APTR)&file->elements.mlh_Tail;
opening->block_pos=0;
opening->pos=new_length;
}
}
/* Re-establish old seek position */
CmdSeek(opening,old_pos,OFFSET_BEGINNING);
/* Store new file size */
if(new_length!=-1)
file->length=new_length;
handler->block_count+=file->block_count-block_count;
SetIoErr(error);
return new_length;
}
/****i* ram.handler/ReadData ***********************************************
*
* NAME
* ReadData --
*
* SYNOPSIS
* read_length = ReadData(opening,buffer,length)
*
* UPINT ReadData(struct Opening *,UBYTE *,UPINT);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
UPINT ReadData(struct Opening *opening,UBYTE *buffer,UPINT length)
{
struct Block *block;
UPINT block_pos,block_length,read_length=0,remainder;
struct Object *file;
/* Fill buffer until request has been fulfilled or EOF is reached */
block=opening->block;
block_pos=opening->block_pos;
file=opening->file;
remainder=file->length-opening->pos;
if(length>remainder)
length=remainder;
remainder=length;
#if 0
ahead=file->length-opening->pos;
if(length>ahead)
length=ahead;
length=remainder;
if(opening->pos+length>file->length)
length=file->length-opening->pos;
remainder=length;
if(opening->pos+length>file->length)
length=file->length-opening->pos;
remainder=length;
#endif
while(remainder>0)
{
/* Get number of remaining valid bytes in this block */
block_length=GetBlockLength(file,block);
block_length-=block_pos;
/* Copy block contents into the caller's buffer */
read_length=MIN(remainder,block_length);
CopyMem(((UBYTE *)block)+sizeof(struct Block)+block_pos,buffer,
read_length);
remainder-=read_length;
buffer+=read_length;
/* Get next block */
if(read_length==block_length)
{
block=(struct Block *)((struct MinNode *)block)->mln_Succ;
block_pos=0;
read_length=0;
}
}
/* Record new position for next access */
opening->block=block;
opening->block_pos=block_pos+read_length;
opening->pos+=length;
/* Return number of bytes read */
return length;
}
/****i* ram.handler/WriteData **********************************************
*
* NAME
* WriteData --
*
* SYNOPSIS
* write_length = WriteData(handler,opening,buffer,length)
*
* UPINT WriteData(struct Handler *,struct Opening *,UBYTE *,UPINT);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
UPINT WriteData(struct Handler *handler,struct Opening *opening,
UBYTE *buffer,UPINT length)
{
struct Block *block,*end_block;
struct Object *file;
UPINT block_pos,block_length,write_length,remainder=length,block_count,
file_length,pos;
LONG error=0;
file=opening->file;
file_length=file->length;
block_count=file->block_count;
pos=opening->pos;
block=opening->block;
block_pos=opening->block_pos;
/* If at EOF, go back to use up any space left in last block */
if((pos==file_length)&&(pos!=0))
{
block=(struct Block *)((struct MinNode *)block)->mln_Pred;
block_pos=file->end_length;
}
while((remainder>0)&&(block!=NULL)&&(error==0))
{
/* Add another block to the file if required */
if(((struct MinNode *)block)->mln_Succ==NULL)
{
block=AddDataBlock(handler,opening->file,remainder);
file->end_length=0;
}
/* Write as much as possible to the current block */
if(block!=NULL)
{
block_length=block->length-block_pos;
write_length=MIN(remainder,block_length);
CopyMem(buffer,((UBYTE *)block)+sizeof(struct Block)+block_pos,
write_length);
remainder-=write_length;
buffer+=write_length;
block_pos+=write_length;
/* Move on to next block if end of current block reached */
if(write_length==block_length)
{
block=(struct Block *)((struct MinNode *)block)->mln_Succ;
/* block_length=block->length;*/
block_pos=0;
}
}
else
error=IoErr();
}
/* Recalculate length of used portion of last block */
end_block=(struct Block *)file->elements.mlh_TailPred;
if((block==end_block)&&(block_pos>file->end_length))
{
file->end_length=block_pos;
block=(struct Block *)((struct MinNode *)block)->mln_Succ;
block_pos=0;
}
else if((struct Block *)((struct MinNode *)block)->mln_Pred==end_block)
file->end_length=end_block->length;
/* Update file size, volume size and current position */
length-=remainder;
pos+=length;
if(pos>file_length)
file->length=pos;
opening->pos=pos;
opening->block=block;
opening->block_pos=block_pos;
handler->block_count+=file->block_count-block_count;
/* Return number of bytes written */
SetIoErr(error);
return length;
}
#if 0
UPINT WriteData(struct Handler *handler,struct Opening *opening,
UBYTE *buffer,UPINT length)
{
struct Block *block,*end_block;
struct Object *file;
UPINT block_pos,block_length,write_length,remainder=length,file_length,
block_count,pos;
LONG error=0;
file=opening->file;
block_count=file->block_count;
file_length=file->length;
block=opening->block;
block_pos=opening->block_pos;
while((remainder>0)&&(block!=NULL))
{
/* Add another block to the file if required */
if(((struct MinNode *)block)->mln_Succ==NULL)
{
block=AddDataBlock(handler,opening->file,remainder);
file->end_length=0;
}
/* Write as much as possible to the current block */
if(block!=NULL)
{
block_length=block->length-block_pos;
write_length=MIN(remainder,block_length);
CopyMem(buffer,((UBYTE *)block)+sizeof(struct Block)+block_pos,
write_length);
remainder-=write_length;
buffer+=write_length;
block_pos+=write_length;
/* Move on to next block if end of current block has been reached */
if(write_length==block_length)
{
block=(struct Block *)((struct MinNode *)block)->mln_Succ;
block_length=block->length;
block_pos=0;
}
}
else
error=IoErr();
}
/* Recalculate length of used portion of last block */
end_block=(struct Block *)file->elements.mlh_TailPred;
if((block==end_block)&&(block_pos>file->end_length))
file->end_length=block_pos;
if((struct Block *)((struct MinNode *)block)->mln_Pred==end_block)
file->end_length=end_block->length;
/* Update file size, volume size and current position */
pos=opening->pos;
length-=remainder;
pos+=length;
if(pos>file_length)
file->length=pos;
opening->pos=pos;
opening->block=block;
opening->block_pos=block_pos;
handler->block_count+=file->block_count-block_count;
/* Return number of bytes written */
SetIoErr(error);
return length;
}
#endif
/****i* ram.handler/LockObject *********************************************
*
* NAME
* LockObject --
*
* SYNOPSIS
* lock = LockObject(handler,object,
* access)
*
* struct Lock *LockObject(struct Handler *handler,struct Object *,
* LONG);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
struct Lock *LockObject(struct Handler *handler,struct Object *object,
LONG access)
{
struct Lock *lock;
LONG error,lock_access;
object=GetRealObject(object);
lock=object->lock;
if(lock==NULL)
{
lock=AllocMem(sizeof(struct Lock),MEMF_PUBLIC|MEMF_CLEAR);
if(lock!=NULL)
{
object->lock=lock;
((struct FileLock *)lock)->fl_Key=(PINT)object;
((struct FileLock *)lock)->fl_Access=access;
((struct FileLock *)lock)->fl_Task=handler->proc_port;
((struct FileLock *)lock)->fl_Volume=MKBADDR(handler->volume);
}
else
error=IoErr();
}
/*#ifndef AMIGAOS*/
else
{
lock_access=((struct FileLock *)lock)->fl_Access;
if((access==ACCESS_WRITE)||(lock_access==ACCESS_WRITE))
{
lock=NULL;
error=ERROR_OBJECT_IN_USE;
}
}
/*#endif*/
if(lock!=NULL)
{
lock->lock_count++;
handler->lock_count++;
}
SetIoErr(error);
return lock;
}
/****i* ram.handler/ExamineObject ******************************************
*
* NAME
* ExamineObject --
*
* SYNOPSIS
* success = ExamineObject(handler,object,
* info)
*
* BOOL ExamineObject(struct Handler *,struct Object *,
* struct FileInfoBlock *);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
BOOL ExamineObject(struct Handler *handler,struct Object *object,
struct FileInfoBlock *info)
{
BOOL success;
struct Object *next_object;
STRPTR s;
LONG entry_type;
if(object==NULL)
{
object=(struct Object *)info->fib_DiskKey;
next_object=(APTR)((struct Node *)object)->ln_Succ;
}
else
next_object=(APTR)object->elements.mlh_Head;
if(next_object!=NULL)
{
/* Fill in information from object */
entry_type=((struct Node *)object)->ln_Pri;
info->fib_DirEntryType=entry_type;
info->fib_EntryType=entry_type;
s=((struct Node *)object)->ln_Name;
CopyMem(MkBStr(s),&info->fib_FileName,StrSize(s));
s=object->comment;
if(s!=NULL)
CopyMem(MkBStr(s),&info->fib_Comment,StrLen(s)+1);
else
info->fib_Comment[0]='\0';
info->fib_NumBlocks=object->block_count;
/* Fill in information from real object */
object=GetRealObject(object);
info->fib_Protection=object->protection;
info->fib_Size=object->length;
CopyMem(&object->date,&info->fib_Date,sizeof(struct DateStamp));
/* Prepare for next examination */
success=TRUE;
info->fib_DiskKey=(PINT)next_object;
}
else
{
success=FALSE;
SetIoErr(ERROR_NO_MORE_ENTRIES);
}
return success;
}
/****i* ram.handler/SetName ************************************************
*
* NAME
* SetName --
*
* SYNOPSIS
* success = SetName(handler,object,name)
*
* BOOL SetName(struct Handler *,struct Object *,TEXT *);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
BOOL SetName(struct Handler *handler,struct Object *object,
const TEXT *name)
{
LONG error;
const TEXT *p;
TEXT ch;
struct Locale *locale;
PINT block_diff;
error=0;
/* Check name isn't too long */
if(StrSize(name)>sizeof(((struct FileInfoBlock *)NULL)->fib_FileName))
error=ERROR_INVALID_COMPONENT_NAME;
/* Check name doesn't have any strange characters in it */
locale=handler->locale;
for(p=name;(ch=*p)!='\0';p++)
if(!IsPrint(locale,ch)||IsCntrl(locale,ch)||(ch==':'))
error=ERROR_INVALID_COMPONENT_NAME;
/* Store new name */
if(error==0)
{
block_diff=SetString(&((struct Node *)object)->ln_Name,name);
if(block_diff==-1)
error=IoErr();
else
{
object->block_count+=block_diff;
handler->block_count+=block_diff;
}
}
/* Return success indicator */
SetIoErr(error);
return error==0;
}
/****i* ram.handler/FixLock ************************************************
*
* NAME
* FixLock --
*
* SYNOPSIS
* fixed_lock = FixLock(handler,lock)
*
* struct Lock *FixLock(struct Handler *,struct Lock *);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
struct Lock *FixLock(struct Handler *handler,struct Lock *lock)
{
if(lock==NULL)
lock=handler->root_dir->lock;
return lock;
}
/****i* ram.handler/AddDataBlock *******************************************
*
* NAME
* AddDataBlock --
*
* SYNOPSIS
* block = AddDataBlock(file,length)
*
* struct Block *AddDataBlock(struct Object *,UPINT);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
* Attempts to allocate a smaller block if the requested size cannot be
* obtained.
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
struct Block *AddDataBlock(struct Handler *handler,struct Object *file,
UPINT length)
{
struct Block *block;
UPINT alloc_size;
ULONG limit;
/* Ensure block size is within limits */
alloc_size=sizeof(struct Block)+length;
limit=handler->max_block_size;
if(alloc_size>limit)
alloc_size=limit;
limit=handler->min_block_size;
if(alloc_size<limit)
alloc_size=limit;
/* Allocate a multiple of the memory block size */
block=NULL;
while((block==NULL)&&(alloc_size>=limit))
{
alloc_size=((alloc_size-1)&(~MEM_BLOCKMASK))+MEM_BLOCKSIZE;
block=AllocMem(alloc_size,MEMF_ANY);
if(block==NULL)
alloc_size>>=1;
}
/* Add the block to the end of the file */
if(block!=NULL)
{
AddTail((struct List *)&file->elements,(struct Node *)block);
block->length=alloc_size-sizeof(struct Block);
file->block_count+=alloc_size>>MEM_BLOCKSHIFT;
}
else
SetIoErr(ERROR_DISK_FULL);
/* Return the new block */
return block;
}
/****i* ram.handler/FreeDataBlock ******************************************
*
* NAME
* FreeDataBlock --
*
* SYNOPSIS
* FreeDataBlock(file,block)
*
* VOID FreeDataBlock(struct Object *,struct Block *);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
VOID FreeDataBlock(struct Object *file,struct Block *block)
{
UPINT alloc_size;
if(block!=NULL)
{
alloc_size=sizeof(struct Block)+block->length;
file->block_count-=alloc_size>>MEM_BLOCKSHIFT;
FreeMem(block,alloc_size);
}
return;
}
/****i* ram.handler/GetRealObject ******************************************
*
* NAME
* GetRealObject --
*
* SYNOPSIS
* real_object = GetRealObject(object)
*
* struct Object *GetRealObject(struct Object *);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
struct Object *GetRealObject(struct Object *object)
{
struct MinNode *node,*pred;
/* Get first node in list */
node=&object->hard_link;
if(node->mln_Pred!=NULL)
{
while((pred=node->mln_Pred)!=NULL)
node=pred;
node=node->mln_Succ;
}
/* Get object from node address */
object=HARDLINK(node);
return object;
}
/****i* ram.handler/GetRealObject ******************************************
*
* NAME
* GetBlockLength --
*
* SYNOPSIS
* length = GetBlockLength(file,block)
*
* UPINT GetBlockLength(struct Object *,struct Block *);
*
* FUNCTION
*
* INPUTS
*
* RESULT
*
* EXAMPLE
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
****************************************************************************
*
*/
UPINT GetBlockLength(struct Object *file,struct Block *block)
{
UPINT length;
if(block==(APTR)file->elements.mlh_TailPred)
length=file->end_length;
else if(((struct MinNode *)block)->mln_Succ==NULL)
length=0;
else
length=block->length;
return length;
}